package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.canstants.SystemCanstants;
import org.example.domain.entity.Article;
import org.example.domain.entity.User;
import org.example.enmus.AppHttpCodeEnum;
import org.example.domain.entity.Comment;
import org.example.domain.result.ResponseResult;
import org.example.domain.vo.CommentVo;
import org.example.domain.vo.PageVo;
import org.example.exception.SystemException;
import org.example.mapper.CommentMapper;
import org.example.service.ArticleService;
import org.example.service.CommentService;
import org.example.service.UserService;
import org.example.utils.BeanCopyUtils;
import org.example.utils.SensitiveWordFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.util.HtmlUtils;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static org.example.canstants.SystemCanstants.ARTICLE_STATUS_DRAFT;

/**
 * @author lemon
 */
@Service("commentService")
@Slf4j
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Autowired
    //根据userid查询用户信息，也就是查username
    private UserService userService;
    @Autowired
    private ArticleService articleService;

    @Override
    public ResponseResult commentList(String commentType, Long articleId, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //对articleId进行判断，作用是得到指定的文章。如果是文章评论，才会判断articleId，避免友链评论判断articleId时出现空指针
        queryWrapper.eq(SystemCanstants.ARTICLE_COMMENT.equals(commentType),Comment::getArticleId,articleId);
        //根评论 rootid 为-1
        queryWrapper.eq(Comment::getRootId, SystemCanstants.Comment_RootId);
        //文章的评论，避免查到友链的评论
        queryWrapper.eq(Comment::getType,commentType);
        //分页查询
        Page<Comment> page = new Page<>(pageNum,pageSize);
        page(page,queryWrapper);

        //调用下面那个方法。根评论排序
        List<Comment> sortedComments = page.getRecords().stream()
                .sorted(Comparator.comparing(Comment::getCreateTime).reversed())
                .collect(Collectors.toList());
        List<CommentVo> commentVoList = toCommentList(sortedComments);

        //遍历(可以用for循环，也可以用stream流)。查询子评论(注意子评论只查到二级评论，不再往深查)
        //查询所有根评论对应的子评论集合，并赋值给对应属性
        for(CommentVo commentVo : commentVoList){
            //查询子评论
            List<CommentVo> children = getChildren(commentVo.getId());
            //把查到的children子评论集的集合，赋值给commentVo类的children字段
            commentVo.setChildren(children);
        }

        return ResponseResult.okResult(new PageVo(commentVoList,page.getTotal()));
    }

    /**
     * 根据根评论id查询子评论的集合
     * @param id
     * @return
     */
    private List<CommentVo> getChildren(Long id){
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getRootId,id);
        //对子评论按照时间进行排序
        queryWrapper.orderByDesc(Comment::getCreateTime);
        List<Comment> comments = list(queryWrapper);
        List<CommentVo> commentVos = toCommentList(comments);
        return commentVos;


    }

    private List<CommentVo> toCommentList(List<Comment> list){
        if (list == null || list.isEmpty()) {
            return Collections.emptyList(); // 避免空列表导致的NPE
        }
        //获取评论区的所有评论
        List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);
        //遍历。由于封装响应好的数据里面没有username字段，所以我们还不能返回给前端。这个遍历就是用来得到username字段
        for (CommentVo commentVo : commentVos) {
            // 处理评论者昵称
            User commentUser = userService.getById(commentVo.getCreateBy());
            if (commentUser != null) { // 判空
                commentVo.setUsername(commentUser.getNickName());
            } else {
                commentVo.setUsername("匿名用户"); // 默认值
                log.warn("用户ID {} 不存在", commentVo.getCreateBy()); // 记录日志便于排查
            }

            // 处理根评论的用户昵称（toCommentUserId != -1 表示是子评论）
            if (commentVo.getToCommentUserId() != -1) {
                User toCommentUser = userService.getById(commentVo.getToCommentUserId());
                if (toCommentUser != null) { // 判空
                    commentVo.setToCommentUserName(toCommentUser.getNickName());
                } else {
                    commentVo.setToCommentUserName("匿名用户"); // 默认值
                    log.warn("被回复用户ID {} 不存在", commentVo.getToCommentUserId());
                }
            }
        }
        return commentVos;
    }

    /**
     * 添加评论
     * @param comment
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务管理
    public ResponseResult addComment(Comment comment) {
        try {
            //1.基础参数校验
            if (comment == null) {
                throw new SystemException(AppHttpCodeEnum.PARAM_INVALID);
            }
            if (!StringUtils.hasText(comment.getContent())) {
                //AppHttpCodeEnum是我们写的枚举类，CONTENT_NOT_NULL代表提示''
                throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
            }
            //2.校验关联数据完整性
            validateCommentData(comment);
            // 3. 内容安全处理
            processContentSecurity(comment);
            // 4. 保存评论
            boolean isSaved = save(comment);
            if (!isSaved) {
                log.error("评论保存失败: {}", comment);
                throw new SystemException(AppHttpCodeEnum.SAVE_FAILED);
            }
            log.info("新增评论成功, ID: {}", comment.getId());
            return ResponseResult.okResult();
        } catch (SystemException e) {
            throw e; // 已知业务异常直接抛出
        } catch (Exception e) {
            log.error("新增评论未知异常: ", e);
            throw new SystemException(AppHttpCodeEnum.SYSTEM_ERROR);
        }
    }

    /**
     * 删除评论
     * @param id
     * @return
     */
    @Override
    public ResponseResult deleteComment(Long id) {
        return null;
    }

    /**
     * 修改评论
     * @param id
     * @param comment
     * @return
     */

    @Override
    public ResponseResult updateComment(Long id, Comment comment) {
        return null;
    }

    /**
     * 校验评论关联数据是否有效
     */
    private void validateCommentData(Comment comment) {
        // 校验用户必须存在
        if (comment.getCreateBy() == null || userService.getById(comment.getCreateBy()) == null) {
            throw new SystemException(AppHttpCodeEnum.USER_NOT_EXIST);
        }

        // 如果关联文章，校验文章必须存在
        if (comment.getArticleId() != null && comment.getArticleId() > 0) {
            Article article = articleService.getById(comment.getArticleId());
            if (article == null || article.getStatus().equals(ARTICLE_STATUS_DRAFT)) {
                throw new SystemException(AppHttpCodeEnum.ARTICLE_NOT_EXIST);
            }
        }

        // 校验父评论是否存在（如果是回复）
        if (comment.getRootId()!= null && comment.getRootId() > 0) {
            Comment parentComment = getById(comment.getRootId());
            if (parentComment == null) {
                throw new SystemException(AppHttpCodeEnum.PARENT_COMMENT_NOT_EXIST);
            }
        }
    }

    /**
     * 内容安全处理
     */
    private void processContentSecurity(Comment comment) {
        // 敏感词过滤
        String filteredContent = SensitiveWordFilter.filter(comment.getContent());
        comment.setContent(filteredContent);

        // HTML标签转义（防止XSS攻击）
        comment.setContent(HtmlUtils.htmlEscape(comment.getContent()));

        // 长度限制（根据数据库字段定义）
        if (comment.getContent().length() > 1024) {
            throw new SystemException(AppHttpCodeEnum.CONTENT_TOO_LONG);
        }
    }
}
